/*******************************************
 * Copyright 2007 Aphrodite Framework for javaME .
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * Email : owner@aphroditeme.dev.java.net
 * Contributors:
 *     Kent Elton - initial API and implementation
 *******************************************/

package com.aphrodite.ui.graphics;

import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.Image;

import com.aphrodite.util.BitmapFont;
import com.aphrodite.util.math.MathUtil;

/**
 * Extensions to <code>Graphics</code> class
 * <p>
 * Allows you to extend the capabilities of the <code>Graphics</code> class by
 * providing routines for polygon rendering, directional string rendering etc.
 * </p>
 * 
 * @see javax.microedition.lcdui.Graphics
 * 
 * @author kentelt
 * 
 */
public final class GraphicUtil {
	/**
	 * Center position a graphics entity
	 * <p>
	 * 
	 * @see GraphicUtil#drawString(Graphics, String, int, int, int, int, int)
	 * @see GraphicUtil#drawString(Graphics, String, int, int,
	 *      com.aphrodite.util.BitmapFont, int, int, int)
	 * @see Graphic3DUtil#drawString(Graphics, String, int, int, int, int, int,
	 *      int)
	 * @see Graphic3DUtil#drawString(Graphics, com.aphrodite.util.BitmapFont,
	 *      String, int, int, int, int, int, int) </p>
	 */
	public static final byte DIR_CENTER = 64;

	/**
	 *Position a graphics entity at the bottom *
	 * <p>
	 * 
	 * @see GraphicUtil#drawString(Graphics, String, int, int, int, int, int)
	 * @see GraphicUtil#drawString(Graphics, String, int, int,
	 *      com.aphrodite.util.BitmapFont, int, int, int)
	 * @see Graphic3DUtil#drawString(Graphics, String, int, int, int, int, int,
	 *      int)
	 * @see Graphic3DUtil#drawString(Graphics, com.aphrodite.util.BitmapFont,
	 *      String, int, int, int, int, int, int) </p>
	 */
	public static final byte DIR_DOWN = 8;
	/**
	 * Vertical direction *
	 * <p>
	 * 
	 * @see GraphicUtil#drawString(Graphics, String, int, int, int, int, int)
	 * @see GraphicUtil#drawString(Graphics, String, int, int,
	 *      com.aphrodite.util.BitmapFont, int, int, int)
	 * @see Graphic3DUtil#drawString(Graphics, String, int, int, int, int, int,
	 *      int)
	 * @see Graphic3DUtil#drawString(Graphics, com.aphrodite.util.BitmapFont,
	 *      String, int, int, int, int, int, int) </p>
	 */
	public static final byte DIR_HORZ = 1;
	/**
	 * Horizontal direction *
	 * <p>
	 * 
	 * @see GraphicUtil#drawString(Graphics, String, int, int, int, int, int)
	 * @see GraphicUtil#drawString(Graphics, String, int, int,
	 *      com.aphrodite.util.BitmapFont, int, int, int)
	 * @see Graphic3DUtil#drawString(Graphics, String, int, int, int, int, int,
	 *      int)
	 * @see Graphic3DUtil#drawString(Graphics, com.aphrodite.util.BitmapFont,
	 *      String, int, int, int, int, int, int) </p>
	 */
	public static final byte DIR_LEFT = 16;
	/**
	 * Right position a grpahics entity *
	 * <p>
	 * 
	 * @see GraphicUtil#drawString(Graphics, String, int, int, int, int, int)
	 * @see GraphicUtil#drawString(Graphics, String, int, int,
	 *      com.aphrodite.util.BitmapFont, int, int, int)
	 * @see Graphic3DUtil#drawString(Graphics, String, int, int, int, int, int,
	 *      int)
	 * @see Graphic3DUtil#drawString(Graphics, com.aphrodite.util.BitmapFont,
	 *      String, int, int, int, int, int, int) </p>
	 */
	public static final byte DIR_RIGHT = 32;
	/**
	 * Position a graphics entity upwards *
	 * <p>
	 * 
	 * @see GraphicUtil#drawString(Graphics, String, int, int, int, int, int)
	 * @see GraphicUtil#drawString(Graphics, String, int, int,
	 *      com.aphrodite.util.BitmapFont, int, int, int)
	 * @see Graphic3DUtil#drawString(Graphics, String, int, int, int, int, int,
	 *      int)
	 * @see Graphic3DUtil#drawString(Graphics, com.aphrodite.util.BitmapFont,
	 *      String, int, int, int, int, int, int) </p>
	 */
	public static final byte DIR_UP = 4;
	/**
	 * Vertical direction *
	 * <p>
	 * 
	 * @see GraphicUtil#drawString(Graphics, String, int, int, int, int, int)
	 * @see GraphicUtil#drawString(Graphics, String, int, int,
	 *      com.aphrodite.util.BitmapFont, int, int, int)
	 * @see Graphic3DUtil#drawString(Graphics, String, int, int, int, int, int,
	 *      int)
	 * @see Graphic3DUtil#drawString(Graphics, com.aphrodite.util.BitmapFont,
	 *      String, int, int, int, int, int, int) </p>
	 */
	public static final byte DIR_VERT = 2;

	/**
	 * Draw a circle
	 * 
	 * @param g
	 *            Graphics context
	 * @param x
	 *            coordinate of the <code>radius</code>
	 * @param y
	 *            coordinate of the <code>radius</code>
	 * @param radius
	 *            of the circle
	 */
	public static void drawCircle(final Graphics g, final int x, final int y, final int radius) {
		g.drawArc(x - radius / 2, y - radius / 2, radius, radius, 0, 360);
	}

	/**
	 * 
	 * @param g
	 *            Graphics context
	 * @param startColor
	 *            of the Gradient
	 * @param endColor
	 *            of the Gradient
	 * @param isVertical
	 *            is
	 * @param x
	 * @param y
	 * @param width
	 * @param height
	 * @param arcWidth
	 */
	final static void drawGradientRoundRect(final Graphics g, int startColor, int endColor, boolean isVertical, int x,
			int y, int width, int height, int arcWidth) {
		if (height < 15)
			return;

		g.translate(x, y);
		int[] colors = com.aphrodite.image.ColorUtil.getGradient(startColor, endColor, height);
		double bend = arcWidth / 3;
		System.out.println("Number of bend lines " + Math.floor(bend));
		int yPos = 0;

		// for(int i=0;i<bend;i++){
		//			
		// } g.setColor(colors[yPos]);
		g.drawLine(7, yPos, width - 7, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(5, yPos, width - 5, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(3, yPos, width - 3, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(2, yPos, width - 2, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(2, yPos, width - 2, yPos);
		// yPos++;
		// g.setColor(colors[yPos]);
		// g.drawLine(2, yPos, width - 2, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(1, yPos, width - 1, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(1, yPos, width - 1, yPos);
		// yPos++;
		for (int i = 7; i < colors.length - 7; i++) {
			yPos++;
			g.setColor(colors[i]);
			g.drawLine(0, yPos, width - 1, yPos);
			// g.drawLine(i, 0, i, height - 1);

		}
		// Bottom curve
		// yPos++;
		// g.setColor(colors[yPos]);
		// g.drawLine(0, yPos, width, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(1, yPos, width - 1, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(1, yPos, width - 1, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(2, yPos, width - 2, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(2, yPos, width - 2, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(3, yPos, width - 3, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(5, yPos, width - 5, yPos);
		yPos++;
		g.setColor(colors[yPos]);
		g.drawLine(7, yPos, width - 7, yPos);
		// g.setColor(0x00ff00);
		// g.drawRoundRect(0, 0, width, height, 20, 10);
		g.translate(-x, -y);
	}

	/**
	 * Draw a polygon
	 * 
	 * @param g
	 * @param points
	 */
	public static void drawPolygon(Graphics g, com.aphrodite.util.geom.Point[] points) {
		int[] x = new int[points.length];
		int[] y = new int[points.length];
		for (int i = 0; i < points.length; i++) {
			x[i] = points[i].getX();
			y[i] = points[i].getY();
		}
		drawPolygon(g, x, y);
	}

	/**
	 * Draw a polygon
	 * <p>
	 * <table>
	 * <tr>
	 * <td><img src=../../../resources/polygon.png></td>
	 * </tr>
	 * <tr>
	 * <td>
	 * <code>xPoints</code>={ 10, 150, 150, 10 }<br/><code>yPoints</code>={ 10, 10, 150, 100 }<br/>
	 * <td>
	 * </tr>
	 * </table>
	 * </p>
	 * 
	 * @param g
	 *            Graphics context
	 * @param xPoints
	 *            Array containing the x coordinates of the polygon points
	 * @param yPoints
	 *            Array containing the y coordinates of the polygon points
	 */
	public static void drawPolygon(Graphics g, int[] xPoints, int[] yPoints) {
		int length = xPoints.length - 1;
		for (int i = 0; i < length; i++) {
			g.drawLine(xPoints[i], yPoints[i], xPoints[i + 1], yPoints[i + 1]);
		}
		g.drawLine(xPoints[length], yPoints[length], xPoints[0], yPoints[0]);
	}

	/**
	 * Draw a rectangle with the specified border width.
	 * <p>
	 * The color has to be set before using this method
	 * </p>
	 * 
	 * @param g
	 *            Graphics context
	 * @param borderWidth
	 *            of the rectangle
	 * @param x
	 *            coordinate of the rectangle
	 * @param y
	 *            coordinate of the rectangle
	 * @param width
	 *            of the rectangle
	 * @param height
	 *            of the rectangle
	 */
	public static void drawRect(Graphics g, int borderWidth, int x, int y, int width, int height) {
		// loop thru. since the width is just a pixel wide :(
		for (int b = 0; b < borderWidth; b++) {
			g.drawRect(x + b, y + b, width - b * 2, height - b * 2);
		}

	}

	/**
	 * <p>
	 * Draw a rectangle with specified border width and transparency level
	 * </p>
	 * Not advisable to use If the target platform natively supports
	 * transparency on drawing primitives.<br/> if transparency is not needed
	 * use
	 * <code>drawRectangle(Graphics g, int color, int borderWidth, int x, int y, int width, int height)</code>
	 * 
	 * 
	 * @param g
	 * @param alphaLevel
	 *            The transparency between 0 (fully transparent) and 255 (fully
	 *            opaque)
	 * @param borderWidth
	 *            of the rectangle (in pixels)
	 * @param x
	 *            coordinate of the rectangle
	 * @param y
	 *            coordinate of the rectangle
	 * @param width
	 *            of the rectangle
	 * @param height
	 *            of the rectangle
	 * @throws IllegalArgumentException
	 *             if the borderWidth is <1
	 * @author kentelt
	 */
	public static void drawRect(Graphics g, int alphaLevel, int borderWidth, int x, int y, int width, int height) {
		if (borderWidth < 1) {
			throw new IllegalArgumentException();
		}
		int color = com.aphrodite.image.ColorUtil.setTransparency(g.getColor(), alphaLevel);
		int[] argb = new int[width * height];
		for (int w = 0; w < borderWidth; w++) {
			for (int i = 0; i < height; i++) {
				for (int j = 0; j < width; j++) {
					if (i == 0) {// top line
						argb[(i + w * width) + j] = color;
					} else if (i == height - 1) {// bottom line
						argb[((i - w) * width) + j] = color;
					} else if (j == 0) {// left line
						argb[(i * width) + (j + w)] = color;
					} else if (j == width - 1) {// right line
						argb[(i * width) + (j - w)] = color;
					}
				}
			}
		}
		g.drawRGB(argb, 0, width, x, y, width, height, true);
	}

	private static void drawString(Graphics g, Image image, int direction, int x, int y)
			throws IllegalArgumentException {
		if (((direction & DIR_LEFT) == DIR_LEFT) && ((direction & DIR_RIGHT) == DIR_RIGHT)) {
			throw new IllegalArgumentException("Invalid combination: LEFT|RIGHT");
		}
		if ((direction & DIR_VERT) == DIR_VERT) {/* Draw Text vertically */
			System.out.println("vert");
			if ((direction & DIR_HORZ) == DIR_HORZ) {
				throw new IllegalArgumentException("Invalid combination: HORZ|VERT");
			}
			if ((direction & DIR_UP) == DIR_UP) {/*
												 * Draw text upwards or
												 * downwards
												 */
				System.out.println("up");
				image = com.aphrodite.image.ImageTransformation.rotateSimple(image, 270);
			} else {
				System.out.println("down");
				image = com.aphrodite.image.ImageTransformation.rotateSimple(image, 90);
			}
		} else {/* Draw Text horz */
			if ((direction & DIR_VERT) == DIR_VERT) {
				throw new IllegalArgumentException("Invalid combination: VERT|HORZ");
			}
			if ((direction & DIR_UP) == DIR_UP) {
				image = com.aphrodite.image.ImageTransformation.rotate(image, 45);
			} else if ((direction & DIR_DOWN) == DIR_DOWN) {
				image = com.aphrodite.image.ImageTransformation.rotate(image, -45);

			}
		}
		if ((direction & DIR_LEFT) == DIR_LEFT) {
			if ((direction & DIR_CENTER) == DIR_CENTER)
				throw new IllegalArgumentException("Invalid combination: LEFT|CENTER");
			x -= image.getWidth();
		} else if ((direction & DIR_CENTER) == DIR_CENTER) {
			if ((direction & DIR_LEFT) == DIR_LEFT)
				throw new IllegalArgumentException("Invalid combination: CENTER|LEFT");
			x -= image.getWidth() / 2;
		}
		g.drawImage(image, x, y, 0);
	}

	/**
	 * Draw text in various directions using Bitmap font
	 * 
	 * @param g
	 *            Graphics context
	 * @param text
	 *            to draw
	 * @param bgColor
	 *            Text background color
	 * @param font
	 *            Bitmap font
	 * @param direction
	 *            Combination of directions see {@link GraphicUtil#DIR_LEFT},
	 *            {@link GraphicUtil#DIR_RIGHT} , {@link GraphicUtil#DIR_UP},
	 *            {@link GraphicUtil#DIR_DOWN}, {@link GraphicUtil#DIR_CENTER} ,
	 *            {@link GraphicUtil#DIR_HORZ},{@link GraphicUtil#DIR_VERT}
	 * @param x
	 *            coordinate of the text
	 * @param y
	 *            coordinate of the text * @throws IllegalArgumentException if
	 *            invalid <code>direction</code> combinations are encountered
	 * @see BitmapFont
	 */
	public static void drawString(Graphics g, String text, int bgColor, com.aphrodite.util.BitmapFont font,
			int direction, int x, int y) {
		Image tmpImage = Image.createImage(font.stringWidth(text), font.getHeight());
		Graphics g2 = tmpImage.getGraphics();
		g2.setColor(bgColor);
		g2.fillRect(0, 0, tmpImage.getWidth(), tmpImage.getHeight());
		g2.setColor(g.getColor());
		font.drawString(g2, text, 0, 0, 0);
		drawString(g, tmpImage, direction, x, y);
	}

	/**
	 * Draw text in various directions
	 * 
	 * @param g
	 *            Graphics context
	 * @param text
	 *            to draw
	 * @param bgColor
	 *            Text background color
	 * @param direction
	 *            of the text
	 * @param x
	 *            coordinate of the text
	 * @param y
	 *            coordinate of the text
	 * @throws IllegalArgumentException
	 *             if invalid <code>direction</code> combinations are
	 *             encountered
	 */
	public static void drawString(Graphics g, String text, int fgColor, int direction, int x, int y) {
		Image tmpImage = Image.createImage(g.getFont().stringWidth(text), g.getFont().getHeight());
		Graphics g2 = tmpImage.getGraphics();
		g2.setColor(g.getColor());
		g2.fillRect(0, 0, tmpImage.getWidth(), tmpImage.getHeight());
		g2.setColor(fgColor);
		g2.drawString(text, 0, 0, 0);
		drawString(g, tmpImage, direction, x, y);
	}

	public static void drawTriangle(Graphics g, int x1, int y1, int x2, int y2, int x3, int y3) {
		// draw line from p1 to p2
		g.drawLine(x1, y1, x2, y2);
		// draw line from p1 to p3
		g.drawLine(x1, y1, x3, y3);
		// draw line from p2 to p3
		g.drawLine(x2, y2, x3, y3);
	}

	/**
	 * Draw a filled circle.
	 * <p>
	 * The color has to be set before using this method.
	 * </p>
	 * 
	 * @param g
	 *            graphics context
	 * @param x
	 *            coordinate of the radius
	 * @param y
	 *            coordinate of the radius
	 * @param radius
	 *            of the circle
	 */
	public static void fillCircle(final Graphics g, int x, int y, int radius) {
		g.fillArc(x - radius / 2, y - radius / 2, radius, radius, 0, 360);
		// g.setColor(bordercolor);
		// drawCircle(g, x, y, radius);

	}

	/**
	 * Draw a filled polygon.
	 * <p>
	 * The color has to be set before using this method.
	 * <table>
	 * <tr>
	 * <td><img src=../../../resources/fillpolygon.png></td>
	 * </tr>
	 * <tr>
	 * <td>
	 * <code>xPoints</code>={ 10, 150, 150, 10 }<br/><code>yPoints</code>={ 10, 10, 150, 100 }<br/>
	 * <td>
	 * </tr>
	 * </table>
	 * </p>
	 * 
	 * @param g
	 * @param points
	 */
	public static void fillPolygon(Graphics g, com.aphrodite.util.geom.Point[] points) {
		int[] x = new int[points.length];
		int[] y = new int[points.length];
		for (int i = 0; i < points.length; i++) {
			x[i] = points[i].getX();
			y[i] = points[i].getY();
		}
		fillPolygon(g, x, y);
	}

	/**
	 * Draw a filled polygon.
	 * <p>
	 * The color has to be set before using this method
	 * </p>
	 * 
	 * @param g
	 *            the graphics context
	 * @param xPoints
	 *            the x coordinates of the polygon
	 * @param yPoints
	 *            the y coordinates of the polygon
	 * @param color
	 *            the color of the polygon
	 * 
	 */
	public final static void fillPolygon(final Graphics g, int[] xPoints, int[] yPoints) {
		while (xPoints.length > 2) {
			// a, b & c represents a candidate triangle to draw.
			// a is the left-most point of the polygon
			int a = MathUtil.indexOfLeast(xPoints);
			// b is the point after a
			int b = (a + 1) % xPoints.length;
			// c is the point before a
			int c = (a > 0) ? a - 1 : xPoints.length - 1;
			// The value leastInternalIndex holds the index of the left-most
			// polygon point found within the candidate triangle, if any.
			int leastInternalIndex = -1;
			boolean leastInternalSet = false;
			// If only 3 points in polygon, skip the tests
			if (xPoints.length > 3) {
				// Check if any of the other points are within the candidate
				// triangle
				for (int i = 0; i < xPoints.length; i++) {
					if (i != a && i != b && i != c) {
						if (com.aphrodite.util.geom.GeomUtil.withinBounds(xPoints[i], yPoints[i], xPoints[a],
								yPoints[a], xPoints[b], yPoints[b], xPoints[c], yPoints[c])) {
							// Is this point the left-most point within the
							// candidate triangle?
							if (!leastInternalSet || xPoints[i] < xPoints[leastInternalIndex]) {
								leastInternalIndex = i;
								leastInternalSet = true;
							}
						}
					}
				}
			}
			// No internal points found, fill the triangle, and reservoir-dog
			// the polygon
			if (!leastInternalSet) {
				g.fillTriangle(xPoints[a], yPoints[a], xPoints[b], yPoints[b], xPoints[c], yPoints[c]);
				int[][] trimmed = trimEar(xPoints, yPoints, a);
				xPoints = trimmed[0];
				yPoints = trimmed[1];
				// Internal points found, split the polygon into two, using the
				// line between
				// "a" (left-most point of the polygon) and leastInternalIndex
				// (left-most
				// polygon-point within the candidate triangle) and recurse with
				// each new polygon
			} else {
				int[][][] split = split(xPoints, yPoints, a, leastInternalIndex);
				int[][] poly1 = split[0];
				int[][] poly2 = split[1];
				fillPolygon(g, poly1[0], poly1[1]);
				fillPolygon(g, poly2[0], poly2[1]);
				break;
			}
		}
	}

	/**
	 * Fill a rectangle with two colors
	 * 
	 * @param g
	 *            graphics context
	 * @param firstColor
	 *            of the gradient
	 * @param secondColor
	 *            of the gradient
	 * @param isVertical
	 *            is a vertical or horizontal split
	 * @param x
	 *            coordinate of the rectangle
	 * @param y
	 *            coordinate of the rectangle
	 * @param width
	 *            of the rectangle
	 * @param height
	 *            of the rectangle
	 */
	public static void fillRect(final Graphics g, int firstColor, int secondColor, boolean isVertical, int x, int y,
			int width, int height) {
		if (!isVertical) {
			g.setColor(firstColor);
			g.fillRect(x, y, width, height / 2);
			g.setColor(secondColor);
			g.fillRect(x, y + height / 2, width, height / 2);
		} else {
			g.setColor(firstColor);
			g.fillRect(x, y, width / 2, height);
			g.setColor(secondColor);
			g.fillRect(x + width / 2, y, width / 2, height);
		}
	}

	/**
	 * Draws a filled rectangle with the specified transparency value.
	 * <p>
	 * The color has to be set before using this method
	 * </p>
	 * 
	 * @param g
	 *            graphics context
	 * @param alphaLevel
	 *            The transparency between 0 (fully transparent) and 255 (fully
	 *            opaque)
	 * @param x
	 *            coordinate of the rectangle
	 * @param y
	 *            coordinate of the rectangle
	 * @param width
	 *            of the rectangle
	 * @param height
	 *            of the rectangle
	 */
	public static void fillRect(final Graphics g, int alphaLevel, int x, int y, int width, int height) {
		int color = com.aphrodite.image.ColorUtil.setTransparency(g.getColor(), alphaLevel);
		int[] argb = new int[width * height];
		for (int i = 0; i < argb.length; i++) {
			argb[i] = color;
		}
		g.drawRGB(argb, 0, width, x, y, width, height, true);
	}

	// /**
	// * Fill the specified triangle.
	// *
	// * @param g
	// * Graphics context
	// * @param x1
	// * the x coordinate of the first vertex of the triangle
	// * @param y1
	// * the y coordinate of the first vertex of the triangle
	// * @param x2
	// * the x coordinate of the second vertex of the triangle
	// * @param y2
	// * the y coordinate of the second vertex of the triangle
	// * @param x3
	// * the x coordinate of the third vertex of the triangle
	// * @param y3
	// * the y coordinate of the third vertex of the triangle
	// *
	// */
	// public static void fillTriangle(final Graphics g, int x1, int y1, int x2,
	// int y2, int x3, int y3) {
	// int centerX = com.aphrodite.util.geom.GeomUtil.getCenter(x1, x2, x3);
	// int centerY = com.aphrodite.util.geom.GeomUtil.getCenter(y1, y2, y3);
	// boolean isPositionMoved;
	// do {
	// // drawTriangle( x1, y1, x2, y2, x3, y3, g );
	// g.drawLine(x1, y1, x2, y2);
	// g.drawLine(x2, y2, x3, y3);
	// g.drawLine(x3, y3, x1, y1);
	//
	// isPositionMoved = false;
	// if (x1 < centerX) {
	// x1++;
	// isPositionMoved = true;
	// } else if (x1 > centerX) {
	// x1--;
	// isPositionMoved = true;
	// }
	// if (x2 < centerX) {
	// x2++;
	// isPositionMoved = true;
	// } else if (x2 > centerX) {
	// x2--;
	// isPositionMoved = true;
	// }
	// if (x3 < centerX) {
	// x3++;
	// isPositionMoved = true;
	// } else if (x3 > centerX) {
	// x3--;
	// isPositionMoved = true;
	// }
	// if (y1 < centerY) {
	// y1++;
	// isPositionMoved = true;
	// } else if (y1 > centerY) {
	// y1--;
	// isPositionMoved = true;
	// }
	// if (y2 < centerY) {
	// y2++;
	// isPositionMoved = true;
	// } else if (y2 > centerY) {
	// y2--;
	// isPositionMoved = true;
	// }
	// if (y3 < centerY) {
	// y3++;
	// isPositionMoved = true;
	// } else if (y3 > centerY) {
	// y3--;
	// isPositionMoved = true;
	// }
	// } while (isPositionMoved);
	// }

	/**
	 * Retrieves the complementary color to the specified one.
	 * 
	 * @param color
	 *            the original argb color
	 * @return The complementary color with tranparency info preserved
	 */
	public static int getComplementaryColor(int color) {
		return (0xFF000000 & color) | ((255 - ((0x00FF0000 & color) >> 16)) << 16)
				| ((255 - ((0x0000FF00 & color) >> 8)) << 8) | (255 - (0x000000FF & color));
	}

	private static int[][][] split(final int[] xPoints, final int[] yPoints, final int aIndex, final int bIndex) {
		int firstLen, secondLen;
		if (bIndex < aIndex) {
			firstLen = (xPoints.length - aIndex) + bIndex + 1;
		} else {
			firstLen = (bIndex - aIndex) + 1;
		}
		secondLen = (xPoints.length - firstLen) + 2;
		int[][] first = new int[2][firstLen];
		int[][] second = new int[2][secondLen];
		for (int i = 0; i < firstLen; i++) {
			int index = (aIndex + i) % xPoints.length;
			first[0][i] = xPoints[index];
			first[1][i] = yPoints[index];
		}
		for (int i = 0; i < secondLen; i++) {
			int index = (bIndex + i) % xPoints.length;
			second[0][i] = xPoints[index];
			second[1][i] = yPoints[index];
		}
		int[][][] result = new int[2][][];
		result[0] = first;
		result[1] = second;
		return result;
	}

	private static int[][] trimEar(int[] xPoints, int[] yPoints, int earIndex) {
		int[] newXPoints = new int[xPoints.length - 1];
		int[] newYPoints = new int[yPoints.length - 1];
		int[][] newPoly = new int[2][];
		newPoly[0] = newXPoints;
		newPoly[1] = newYPoints;
		int p = 0;
		for (int i = 0; i < xPoints.length; i++) {
			if (i != earIndex) {
				newXPoints[p] = xPoints[i];
				newYPoints[p] = yPoints[i];
				p++;
			}
		}
		return newPoly;
	}

	private GraphicUtil() {}

	// public static void drawShape(final Graphics g, final Shape shape) {
	// if (shape instanceof Rectangle) {
	// g.drawRect(shape.getX(), shape.getY(), ((Rectangle) shape).getWidth(),
	// ((Rectangle) shape).getHeight());
	// } else if (shape instanceof Triangle) {
	// GraphicUtil.
	// }
	// }
}
